package com.paw.gateway.filter;

import java.util.List;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.paw.common.constant.CommonConstant;
import com.paw.common.constant.RedisPrefixKeyConstant;
import com.paw.common.domain.Result;
import com.paw.common.enums.CommonResponseCodeEnum;
import com.paw.common.enums.ICommonEnum;
import com.paw.gateway.enums.GatewayResponseCodeCommonEnum;
import com.paw.gateway.property.AuthFilterProperty;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

/**
 * @author Rubble
 * @date 2021/8/26
 **/
@Slf4j
@Component
public class AuthorizeFilter implements GlobalFilter, Ordered {
  

  @Autowired
  private AuthFilterProperty authFilterProperty;

  @Autowired
  private StringRedisTemplate stringRedisTemplate;

  @Override
  public Mono<Void> filter (ServerWebExchange exchange, GatewayFilterChain chain) {

    List<String> anonUrls = authFilterProperty.getUrls();

    ServerHttpRequest serverHttpRequest = exchange.getRequest();
    ServerHttpResponse serverHttpResponse = exchange.getResponse();
    String path = serverHttpRequest.getURI().getPath();
    AntPathMatcher pathMatcher = new AntPathMatcher();

    // 过滤不拦截路径
    for (String patternUrl : anonUrls) {
      if(pathMatcher.match(patternUrl,path)){
        return chain.filter(exchange);
      }
    }
    String token = serverHttpRequest.getHeaders().getFirst(CommonConstant.TOKEN);
    if(StrUtil.isEmpty(token)){
      token = serverHttpRequest.getQueryParams().getFirst(CommonConstant.TOKEN);
    }
    if(StrUtil.isEmpty(token)){
      return getVoidMono(serverHttpResponse, CommonResponseCodeEnum.UNAUTHORIZED);
    }
    // 验证token
    String tokenKey = RedisPrefixKeyConstant.getKey(RedisPrefixKeyConstant.PRE_TOKEN,token);
    // paw-portal 登录时 用户信息放入redis
    String userInfoStr = stringRedisTemplate.opsForValue().get(tokenKey);
    if(StrUtil.isEmpty(userInfoStr)){
      return getVoidMono(serverHttpResponse, GatewayResponseCodeCommonEnum.TOKEN_INVALID);
    }
    // 将userInfo base64后放入header
    String userInfoEncode = Base64.encode(userInfoStr);
    serverHttpRequest = serverHttpRequest.mutate().header(CommonConstant.USER_INFO, userInfoEncode).build();
    //把新的 exchange放回到过滤链
    return chain.filter(exchange.mutate().request(serverHttpRequest).build());
  }

  @Override
  public int getOrder () {
    return 0;
  }


  private Mono<Void> getVoidMono(ServerHttpResponse serverHttpResponse, ICommonEnum codeEnum) {
    serverHttpResponse.getHeaders().add("Content-Type", "application/json;charset=UTF-8");
    Result<String> responseResult = Result.error(codeEnum.getCode(),codeEnum.getDesc());
    DataBuffer dataBuffer = serverHttpResponse.bufferFactory().wrap(JSON.toJSONString(responseResult).getBytes());
    return serverHttpResponse.writeWith(Flux.just(dataBuffer));
  }


}
